package options

import (
	"fmt"

	"github.com/gin-gonic/gin"
	"github.com/mars/internal/pkg/gins"
	"github.com/spf13/pflag"
)

// GinOptions 描述的是一个 gin server 的配置
type GinOptions struct {
	Port            int    `mapstructure:"port"             json:"port"`
	Mode            string `mapstructure:"mode"             json:"mode"`
	Healthz         bool   `mapstructure:"healthz"          json:"healthz"`
	EnableProfiling bool   `mapstructure:"enable-profiling" json:"enable-profiling"`
	EnableMetrics   bool   `mapstructure:"enable-metrics"   json:"enable-metrics"`
}

func NewGinOptions() *GinOptions {
	return &GinOptions{
		Port:            8762,
		Mode:            gin.ReleaseMode,
		Healthz:         true,
		EnableProfiling: true,
		EnableMetrics:   false,
	}
}

func (opts *GinOptions) AddFlags(fs *pflag.FlagSet) {
	fs.IntVar(&opts.Port, "gin.port", opts.Port, "Specify gin server port.")
	fs.StringVar(&opts.Mode, "gin.mode", opts.Mode, "Specify gin server start mode. test, debug and release is optional.")
	fs.BoolVar(&opts.Healthz, "gin.healthz", opts.Healthz, "Specify gin server healthz, it will register a health api if true.")
	fs.BoolVar(&opts.EnableProfiling, "gin.enable-profiling", opts.EnableProfiling, "Specify gin server profiling, it will register a profiling api if true.")
	fs.BoolVar(&opts.EnableMetrics, "gin.enable-metrics", opts.EnableMetrics, "Specify gin server metrics, it will register a prometheus api if true.")
}

func (opts *GinOptions) Validate() []error {
	var errors = []error{}

	if opts.Mode != gin.TestMode && opts.Mode != gin.DebugMode && opts.Mode != gin.ReleaseMode {
		errors = append(errors, fmt.Errorf("--gin.mode must be is one of %s, %s, %s",
			gin.TestMode, gin.DebugMode, gin.ReleaseMode))
	}
	if opts.Port < 0 || opts.Port > 65535 {
		errors = append(errors, fmt.Errorf("--gin.port must be gt 0 and lt 65535"))
	}

	return errors
}

func (opts *GinOptions) New() *gins.GenericAPIServer {
	server := &gins.GenericAPIServer{
		Port:            opts.Port,
		Mode:            opts.Mode,
		Healthz:         opts.Healthz,
		EnableMetrics:   opts.EnableMetrics,
		EnableProfiling: opts.EnableProfiling,
	}
	server.Setup()
	server.Engine = gin.New()
	return server
}
